/*
 * File: manager.cpp - contains the implementation of manager class
 * Author: Sam Tran (tpmsam@yahoo.com), UHCL, April 2006
 */

#include "manager.h"
#include <cstdio>
#include <crng.h>
#include <cstring>
#include <math.h>



void manager::initialize()
{
	int i,j;
	cModule *mod;
	char tempstring[30];
	int comm_radius = CRADIUS; //communication
	
  
nodepos_struct pos[100];

	// just initialization code...
	for (i=0;i<NNODES;i++)
	{
		for (j=0;j<NNODES;j++)
		{
			cm[i][j] = false;
		}
	}

	// hide the manager from the display
	if (ev.isGUI())
		setDisplayString("p=-20,-20,exact;b=1,1,oval;o=red,red");


//generate positions of the nodes

  for(i=0;i<NNODES-1;i++)
	{
		
		pos[i].x=intrand(SPACEX);
		pos[i].y=intrand(SPACEY);
	
		mod = this->parentModule()->submodule("sn",i);
		mod->par("ID") = i;
		mod->par("PX") = pos[i].x;
		mod->par("PY") = pos[i].y;
		mod->par("OCCUPATION") = 2;
		mod->par("HEAD_DISTRIBUTION")= (100/10);
		if (ev.isGUI())
			{				
		    sprintf(tempstring,"p=%d,%d,exact;b=15,15,oval;o=gray,black",(int)mod->par("PX"),(int)mod->par("PY"));//changed
		    mod->setDisplayString(tempstring);
		  }
	}	
	if(i==99)//node 99 is base
		{
			pos[i].x=320;
			pos[i].y=320;
			mod = this->parentModule()->submodule("sn",i);
			mod->par("ID") = i;
		  mod->par("PX") = pos[i].x;
	  	mod->par("PY") = pos[i].y;
	  	mod->par("OCCUPATION") = 5;
	  	mod->par("HEAD_DISTRIBUTION")= (100/10);
	  	base_ID = i;
			base_index = i;
		  if (ev.isGUI())
		  	{
		     sprintf(tempstring,"i=device/laptop;p=%d,%d,exact",(int)mod->par("PX"),(int)mod->par("PY"));
	       mod->setDisplayString(tempstring);
	      }
			}
			
	cModule *mod1,*mod2;
	//assign distance from node to base (just for energy calculation to transmit from node o base)
	for (i=0;i<NNODES;i++)
	{
		mod1 = this->parentModule()->submodule("sn",i);
		mod2 = this->parentModule()->submodule("sn",base_index);
		if(ceil(sqrt((double)(pow((int)mod1->par("PX") - (int)mod2->par("PX"), 2) + pow((int)mod1->par("PY") - (int)mod2->par("PY"), 2))))> CRADIUS)
			mod1->par("DISTANCE") = ceil(sqrt((double)(pow((int)mod1->par("PX") - (int)mod2->par("PX"), 2) + pow((int)mod1->par("PY") - (int)mod2->par("PY"), 2))));
		else
			mod1->par("DISTANCE") = CRADIUS;
	}

	//// connect this module to whomever is in transmission range (except the base
	
	for(i=0; i< NNODES; i++)
	{
		for (j=0;j<NNODES;j++)
		{
			if((j!=i) && (i!= base_index) && (j!= base_index)) //make sure they are not the base
			{
				mod1 = this->parentModule()->submodule("sn",i);
				mod2 = this->parentModule()->submodule("sn",j);

				// if the two nodes can hear each other then connect them
				if ((cm[i][j]== false) && (comm_radius*comm_radius >=(((int)mod1->par("PX")-(int)mod2->par("PX"))*((int)mod1->par("PX")-(int)mod2->par("PX")) + ((int)mod1->par("PY")-(int)mod2->par("PY"))*((int)mod1->par("PY")-(int)mod2->par("PY")))))
				{
					cGate *gate1 = NULL;
					cGate *gate2 = NULL;

					gate1 = mod1->gate("in",(int)mod2->par("ID"));
					gate2 = mod2->gate("out",(int)mod1->par("ID"));
						
					// connect the gates
					gate1->setFrom(gate2);
					gate2->setTo(gate1);
					//	gate1->setDisplayString("m=m,50,50,50,50;o=#AAA,1;",false);
					//	gate2->setDisplayString("m=m,50,50,50,50;o=#AAA,1;",false);
					gate1->setDisplayString("m=m,30,30,30,30;o=gray,0;",false);
					gate2->setDisplayString("m=m,30,30,30,30;o=gray,0;",false);

					// connect the reverse link
					gate1 = mod1->gate("out",(int)mod2->par("ID"));
					gate2 = mod2->gate("in",(int)mod1->par("ID"));

					gate1->setTo(gate2);
					gate2->setFrom(gate1);
				//		gate1->setDisplayString("m=m,50,50,50,50;o=#AAA,1;",false);
				//		gate2->setDisplayString("m=m,50,50,50,50;o=#AAA,1;",false);
					gate1->setDisplayString("m=m,30,30,30,30;o=gray,0;",false);
					gate2->setDisplayString("m=m,30,30,30,30;o=gray,0;",false);

					// update the data structure
					cm[i][j] = true;
					cm[j][i] = true;
				}
			}
		}
	} 
	cMessage *timer= new cMessage("TIMER"); 
	scheduleAt(simTime()+0.2,timer);
}
void manager::activity()
{
	cMessage* m;	
	int i;	
	cModule *mod1,*mod2;
	cGate *gate1, *gate2;
	// main loop
	while (1)
	{
		m = receive();
		//Connections refresh
		if (strcmp(m->name(),"TIMER")==0)
		{
			//Create connection between base node and cluster head nodes using first gate of node
			for (i=0;i<NNODES;i++)
			{
				mod1 = this->parentModule()->submodule("sn",i);

				if((int)mod1->par("OCCUPATION")==1)//cluster head
				{
					mod1->par("FATHER") = base_ID;

					mod2 = this->parentModule()->submodule("sn",base_index);

					//Connect to the base using the biggest port
					//gate1 = mod1->gate("in",MAXCONN - 1);

					//Connect to the base using the first port
					gate1 = mod1->gate("in",MAXCONN-1);
					
					gate2 = mod2->gate("out",(int)mod1->par("ID"));

					// connect the gates
					gate1->setFrom(gate2);
					gate2->setTo(gate1);

					if (ev.isGUI())
					{
						gate1->setDisplayString("m=a;o=mediumseagreen,1;");
						gate2->setDisplayString("m=a;o=mediumseagreen,1;");
					}

					//connect reverse
					gate1 = mod1->gate ("out", MAXCONN - 1);
					gate2 = mod2->gate("in",(int)mod1->par("ID"));

					gate2->setFrom(gate1);
					gate1->setTo(gate2);

					if (ev.isGUI())
					{
						gate1->setDisplayString("m=a;o=mediumseagreen,1;");
						gate2->setDisplayString("m=a;o=mediumseagreen,1;");
					}

				}
			}

			//if((int)parentModule()->submodule("o")->par("X") < SPACEX && (int)parentModule()->submodule("o")->par("Y") < SPACEY)
			//	scheduleAt(simTime()+ 9000,timer);
			//else //object went out of the zone -->shutdown the network
			//	shutdown();
		}	
		delete m;
	}
	
}
